package com.summer.data.jql.concept.func;

import com.summer.data.Jsql;
import com.summer.data.dialect.Dialect;
import com.summer.data.jql.Context;
import com.summer.data.jql.behavior.FilterAble;
import com.summer.data.jql.concept.Field;
import com.summer.data.jql.concept.Value;
import com.summer.data.jql.concept.exp.OP;
import com.summer.data.jql.concept.exp.OpFilterExp;

import static com.summer.data.jql.concept.exp.OP.*;

/**
 * @author 345480567@qq.com
 */
public class Count<T> implements Field<T> {

    boolean distinct = false;

    Field<T> elem;

    public Count(Field<T> field) {
        this.elem = field;
    }

    public Count distinct(boolean distinct) {
        this.distinct = distinct;
        return this;
    }

    @Override
    public Jsql toFieldSql(Context ctx, Dialect dialect) {
        String format = "COUNT(%s)";
        if (distinct) {
            format = "COUNT(DISTINCT %s)";
        }
        return Jsql.format(format, elem.toFieldSql(ctx, dialect));
    }

    public FilterAble eq(Field field) {
        return op(EQ, field);
    }

    public FilterAble eq(Integer value) {
        return op(EQ, new Value<Integer>(value));
    }

    public FilterAble notEq(Field field) {
        return op(NOTEQ, field);
    }

    public FilterAble notEq(Integer value) {
        return op(NOTEQ, new Value<Integer>(value));
    }

    public FilterAble lt(Field field) {
        return op(LT, field);
    }

    public FilterAble lt(Integer value) {
        return op(LT, new Value<Integer>(value));
    }

    public FilterAble gt(Field field) {
        return op(GT, field);
    }

    public FilterAble gt(Integer value) {
        return op(GT, new Value<Integer>(value));
    }

    public FilterAble ltEq(Field field) {
        return op(LT_EQ, field);
    }

    public FilterAble ltEq(Integer value) {
        return op(LT_EQ, new Value<Integer>(value));
    }

    public FilterAble gtEq(Field field) {
        return op(GT_EQ, field);
    }

    public FilterAble gtEq(Integer value) {
        return op(GT_EQ, new Value<Integer>(value));
    }

    private FilterAble op(OP op, Field field) {
        return new OpFilterExp(op, this, field);
    }

}
